package com.xqls.server.netty;

import com.xqls.server.dto.send.ConcentrationSamplingSetDto;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.PooledByteBufAllocator;
import io.netty.buffer.UnpooledByteBufAllocator;
import io.netty.channel.Channel;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

public class NettyTCPServer extends AbstractNettyServer {
    private static final Logger LOG = LoggerFactory
            .getLogger(NettyTCPServer.class);

    private ServerBootstrap serverBootstrap;

    //客户端的连接保存的map
    private static Map<String, Channel> channelMap = new ConcurrentHashMap<String, Channel>();
    //客户端的key的map
    private static Map<String,String> channelKeyMap = new ConcurrentHashMap<String, String>();


    //浓度采样的的map
    public static Map<String,ConcentrationSamplingSetDto> samplingSetDto = new ConcurrentHashMap<String, ConcentrationSamplingSetDto>();

    public static Map<String, String> getChannelKeyMap() {
        return channelKeyMap;
    }



    public static Map<String, Channel> getChannelMap() {
        return channelMap;
    }


    public static void  checkChannelExsit(String adrress,String key){
      String  existKey=
        channelKeyMap.get(adrress);//已经存在的 channel的key
        if(existKey!=null&&!existKey.equals(key)) {
            Channel exist = channelMap.get(existKey);
            if (exist != null) {
                exist.close();
                channelMap.remove(existKey);
            }
        }
        channelKeyMap.put(adrress,key);
    }

    public static Channel getChannelByAdresss(String address) {
         String  channelKey=channelKeyMap.get(address);
         if(StringUtils.isEmpty(channelKey)){
             return  null;
         }

        return channelMap.get(channelKey);
    }

    public static  String getAdressByChannel(String channelKey){

        if(channelKey!=null&&channelKeyMap.size()>0){
            for (Map.Entry<String,String> entry:channelKeyMap.entrySet()){
                if(channelKey.equals(entry.getValue())){

                    return  entry.getKey();
                }

            }
        }
     return null;
    }


    public NettyTCPServer(NettyConfig nettyConfig,
            ChannelInitializer<? extends Channel> channelInitializer)
    {
        super(nettyConfig, channelInitializer);
    }

    @Override
    public void startServer() throws Exception {
        try {
            serverBootstrap = new ServerBootstrap();
            Map<ChannelOption<?>, Object> channelOptions = nettyConfig.getChannelOptions();
            if(null != channelOptions){
                Set<ChannelOption<?>> keySet = channelOptions.keySet();
                // 获取configuration配置到channelOption
                for(ChannelOption option : keySet)
                {
                    serverBootstrap.option(option, channelOptions.get(option));
                }
                serverBootstrap.option(ChannelOption.ALLOCATOR,UnpooledByteBufAllocator.DEFAULT);
            }
            // reactor多线程模型，配置bossGroup和workGroup
            // bossGroup和workGroup使用spring容器管理
            serverBootstrap.group(getBossGroup(),getWorkerGroup())
                    .channel(NioServerSocketChannel.class)
                    .childHandler(getChannelInitializer());
            // 绑定端口，启动并监听
            Channel serverChannel = serverBootstrap.bind(nettyConfig.getSocketAddress()).sync()
                    .channel();
            ALL_CHANNELS.add(serverChannel);

        } catch(Exception e) {
            LOG.error("TCP Server start error {}, going to shut down", e);
            super.stopServer();
            throw e;
        }
    }

    @Override
    public TransmissionProtocol getTransmissionProtocol() {
        return TRANSMISSION_PROTOCOL.TCP;
    }

    // 配置自己的initializer
    @Override
    public void setChannelInitializer(ChannelInitializer<? extends Channel> initializer) {
        this.channelInitializer = initializer;
        serverBootstrap.childHandler(initializer);
    }

    @Override
    public String toString() {
        return "NettyTCPServer [socketAddress=" + nettyConfig.getSocketAddress()
                + ", portNumber=" + nettyConfig.getPortNumber() + "]";
    }

}